# frozen_string_literal: true
require 'spec_helper'

require_migration!

RSpec.describe PopulateVulnerabilityReads, :migration, feature_category: :vulnerability_management do
  let!(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
  let!(:user) { table(:users).create!(email: 'author@example.com', username: 'author', projects_limit: 10) }
  let!(:project) { table(:projects).create!(namespace_id: namespace.id) }
  let!(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
  let!(:background_migration_jobs) { table(:background_migration_jobs) }
  let!(:vulnerabilities) { table(:vulnerabilities) }
  let!(:vulnerability_reads) { table(:vulnerability_reads) }
  let!(:vulnerabilities_findings) { table(:vulnerability_occurrences) }
  let!(:vulnerability_issue_links) { table(:vulnerability_issue_links) }
  let!(:vulnerability_ids) { [] }

  before do
    stub_const("#{described_class}::BATCH_SIZE", 1)
    stub_const("#{described_class}::SUB_BATCH_SIZE", 1)

    5.times.each do |x|
      vulnerability = create_vulnerability!(
        project_id: project.id,
        report_type: 7,
        author_id: user.id
      )
      identifier = table(:vulnerability_identifiers).create!(
        project_id: project.id,
        external_type: 'uuid-v5',
        external_id: 'uuid-v5',
        fingerprint: Digest::SHA1.hexdigest(vulnerability.id.to_s),
        name: 'Identifier for UUIDv5')

      create_finding!(
        vulnerability_id: vulnerability.id,
        project_id: project.id,
        scanner_id: scanner.id,
        primary_identifier_id: identifier.id
      )

      vulnerability_ids << vulnerability.id
    end
  end

  around do |example|
    freeze_time { Sidekiq::Testing.fake! { example.run } }
  end

  it 'schedules background migrations' do
    migrate!

    expect(background_migration_jobs.count).to eq(5)
    expect(background_migration_jobs.first.arguments).to match_array([vulnerability_ids.first, vulnerability_ids.first, 1])
    expect(background_migration_jobs.second.arguments).to match_array([vulnerability_ids.second, vulnerability_ids.second, 1])
    expect(background_migration_jobs.third.arguments).to match_array([vulnerability_ids.third, vulnerability_ids.third, 1])
    expect(background_migration_jobs.fourth.arguments).to match_array([vulnerability_ids.fourth, vulnerability_ids.fourth, 1])
    expect(background_migration_jobs.fifth.arguments).to match_array([vulnerability_ids.fifth, vulnerability_ids.fifth, 1])

    expect(BackgroundMigrationWorker.jobs.size).to eq(5)
    expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(2.minutes, vulnerability_ids.first, vulnerability_ids.first, 1)
    expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(4.minutes, vulnerability_ids.second, vulnerability_ids.second, 1)
    expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(6.minutes, vulnerability_ids.third, vulnerability_ids.third, 1)
    expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(8.minutes, vulnerability_ids.fourth, vulnerability_ids.fourth, 1)
    expect(described_class::MIGRATION_NAME).to be_scheduled_delayed_migration(10.minutes, vulnerability_ids.fifth, vulnerability_ids.fifth, 1)
  end

  private

  def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
    vulnerabilities.create!(
      project_id: project_id,
      author_id: author_id,
      title: title,
      severity: severity,
      confidence: confidence,
      report_type: report_type
    )
  end

  # rubocop:disable Metrics/ParameterLists
  def create_finding!(
    vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:, id: nil,
    name: "test", severity: 7, confidence: 7, report_type: 0,
    project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
    metadata_version: 'test', raw_metadata: 'test', uuid: SecureRandom.uuid)
    params = {
      vulnerability_id: vulnerability_id,
      project_id: project_id,
      name: name,
      severity: severity,
      confidence: confidence,
      report_type: report_type,
      project_fingerprint: project_fingerprint,
      scanner_id: scanner_id,
      primary_identifier_id: primary_identifier_id,
      location_fingerprint: location_fingerprint,
      metadata_version: metadata_version,
      raw_metadata: raw_metadata,
      uuid: uuid
    }
    params[:id] = id unless id.nil?
    vulnerabilities_findings.create!(params)
  end
  # rubocop:enable Metrics/ParameterLists
end
